#include <iostream>
#include <vector>
#include <string>
#include<cstring>
#include <pthread.h>
#include <unistd.h>
#include "lockGuard.hpp"
using namespace std;

#define NUM 4


// int tickets = 3000;
// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

// class threadData
// {
// public:
//     threadData(int number/*, pthread_mutex_t *lock*/)
//         //:_lock(lock)
//     {
//         _threadName = "thread-" + to_string(number);
//     }

//     string _threadName;
//     //pthread_mutex_t *_lock;
// };

// void *Routine(void *args)
// {
//     threadData *td = static_cast<threadData*>(args);
//     // while(true)
//     // {
//     //     //pthread_mutex_lock(td->_lock);
//     //     pthread_mutex_lock(&lock);
//     //     //pthread_mutex_lock(&lock);
//     //     if(tickets > 0)
//     //     {
//     //         usleep(1000);
//     //         cout << td->_threadName << ", get a ticket, tickets: " << tickets << endl;
//     //         --tickets;
//     //         //pthread_mutex_unlock(td->_lock);
//     //         pthread_mutex_unlock(&lock);
//     //     }
//     //     else
//     //     {
//     //         //pthread_mutex_unlock(td->_lock);
//     //         pthread_mutex_unlock(&lock);
//     //         break;
//     //     }
//     //     usleep(20);
//     // }

//     //封装
//     while(true)
//     {
//         {
//             Guard g(&lock);
//             if(tickets > 0)
//             {
//                 usleep(1000);
//                 cout << td->_threadName << ", get a ticket, tickets: " << tickets << endl;
//                 --tickets;
//                 pthread_mutex_unlock(&lock);
//             }
//             else break;
//         }
//         usleep(20);
//     }

//     cout << td->_threadName << " quit" << endl;
//     return nullptr;
// }

// int main()
// {
//     vector<pthread_t> tids;
//     vector<threadData*> tds;

//     // pthread_mutex_t lock;
//     // pthread_mutex_init(&lock, nullptr);

//     for(int i = 0; i < NUM; ++i)
//     {
//         pthread_t tid;
//         threadData *td = new threadData(i/*, &lock*/);
//         tds.push_back(td);
//         pthread_create(&tid, nullptr, Routine, td);
//         tids.push_back(tid);
//     }
//     for(auto tid : tids)
//     {
//         pthread_join(tid, nullptr);
//     }
//     for(auto td : tds)
//     {
//         delete td;
//     }

//     //pthread_mutex_destroy(&lock);

//     return 0;
// }






//pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int count = 0;
class threadData
{
public:
    threadData(int number, pthread_mutex_t *lock)
        :_lock(lock)
    {
        _threadName = "thread-" + to_string(number);
    }

    string _threadName;
    pthread_mutex_t *_lock;
};

void *Routine(void *args)
{
    threadData *td = static_cast<threadData*>(args);
    while(true)
    {
        //pthread_mutex_lock(&lock);
        pthread_mutex_lock(td->_lock);
        cout << td->_threadName << ", counting: " << count++ << endl;
        //pthread_mutex_unlock(&lock);
        pthread_mutex_unlock(td->_lock);
        if(count >= 6)
            break;
        sleep(1);
    }

    cout << td->_threadName << " quit" << endl;
    return nullptr;
}

int main()
{
    vector<pthread_t> tids;
    vector<threadData*> tds;

    pthread_mutex_t lock;
    pthread_mutex_init(&lock, nullptr);

    for(int i = 0; i < NUM; ++i)
    {
        pthread_t tid;
        threadData *td = new threadData(i, &lock);
        tds.push_back(td);
        pthread_create(&tid, nullptr, Routine, td);
        tids.push_back(tid);
    }
    for(auto tid : tids)
    {
        pthread_join(tid, nullptr);
    }
    cout << "main thread wait thread over" << endl;
    for(auto td : tds)
    {
        delete td;
    }
    cout << "main thread delete thread over" << endl;

    pthread_mutex_destroy(&lock);

    return 0;
}